home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '90 / MacHack'90 Proceedings / John Norstad / Reusable Code / Source / abou.c next >
Encoding:
C/C++ Source or Header  |  1990-06-10  |  15.7 KB  |  521 lines  |  [TEXT/MPS ]

  1. /*______________________________________________________________________
  2.  
  3.     abou.c - About Window Manager.
  4.     
  5.     Copyright © 1988, 1989, 1990 Northwestern University.  Permission is 
  6.     granted to use this code in your own projects, provided you give credit 
  7.     to both John Norstad and Northwestern University in your about box or 
  8.     document.
  9. _____________________________________________________________________*/
  10.  
  11.  
  12. #pragma load "precompile"
  13. #include "utl.h"
  14. #include "rez.h"
  15. #include "glob.h"
  16. #include "wstm.h"
  17. #include "abou.h"
  18. #include "help.h"
  19.  
  20. #pragma segment abou
  21.  
  22. /*______________________________________________________________________
  23.  
  24.     Constant Definitions.
  25. _____________________________________________________________________*/
  26.  
  27.  
  28. /* Movie states. */
  29.  
  30. typedef enum StateType {
  31.     start,                /* start the movie */
  32.     startNameLeft,        /* start sliding virus name left */
  33.     slideNameLeft,        /* slide virus name left */
  34.     slideNamesUp,        /* slide virus names up */
  35.     slideFootDown,        /* slide foot down */
  36.     slideFootUp,        /* slide foot up */
  37. } StateType;
  38.  
  39. /* Timing constants, in ticks and pixels. */
  40.  
  41. #define initWait                300            /* initial wait */
  42. #define deltaNameHScroll    2                /* amount to scroll name left each
  43.                                                         time */
  44. #define deltaNameHTicks        1                /* wait between name scrolls left */
  45. #define deltaNameVScroll    2                /* amount to scroll names up each
  46.                                                         time */
  47. #define deltaNameVTicks        1                /* wait between name scrolls up */
  48. #define footWait                120            /* wait before foot starts coming down */
  49. #define deltaFootVScroll    5                /* amount to scroll foot each time */
  50. #define deltaFootVTicks        1                /* wait between foot scrolls */
  51. #define deltaSquishVTicks  3                /* wait between foot scrolls during
  52.                                                         squishing */
  53.  
  54. /*______________________________________________________________________
  55.  
  56.     Global Variables.
  57. _____________________________________________________________________*/
  58.  
  59.  
  60. static WindowPtr        AbouWindow = nil;    /* ptr to about window */
  61. static WindowRecord    AbouWRecord;        /* about window record */
  62. static WindowObject    AbouWindObject;    /* about window object */
  63. static StateType        State;                /* movie state */
  64. static long                WaitTill;            /* tick count to wait until */
  65. static RgnHandle        UpdateRgn;            /* update region for ScrollRect calls */
  66. static BitMap            FootMap;                /* offscreen foot bitmap */
  67. static GrafPort        NamePort;            /* grafPort for drawing virus names 
  68.                                                         offscreen */
  69. static BitMap            NameMap;                /* offscreen virus names bitmap */
  70. static short            MaxNameWidth;        /* max virus name width */
  71. static short            NamesLeft;            /* left coord of virus names */
  72. static Rect                NamesRect;            /* rectangle enclosing names in NameMap */
  73. static Rect                SquishRect;            /* squished names rectangle */
  74. static Rect                FootCopyRect;        /* rectangle in foot bit map to be copied */
  75. static Rect                AbouCopyRect;        /* rectangle in window to copy
  76.                                                         part of foot to */
  77.  
  78. /*______________________________________________________________________
  79.  
  80.     abou_IsOpen - Check to See if About Window is Open.
  81.     
  82.     Exit:        function result = true if window open.
  83. _____________________________________________________________________*/
  84.  
  85.  
  86. Boolean abou_IsOpen (void)
  87.  
  88. {
  89.     return AbouWindow != nil;
  90. }
  91.  
  92. /*______________________________________________________________________
  93.  
  94.     Update - Process an Update Event.
  95. _____________________________________________________________________*/
  96.  
  97.  
  98. static void Update (void)
  99.  
  100. {
  101.     PicHandle        mePict;                /* handle to my picture */
  102.     Handle            credits;                /* handle to credits STR# rsrc */
  103.     char                creditsStr[600];    /* credits string */
  104.     char                *pCreditsStr;        /* pointer into credits string */
  105.     char                *pCreditsRsrc;        /* pointer into credits STR# rsrc */
  106.     short                nCreditsStr;        /* number of strings in credits rsrc */
  107.     short                strLen;                /* length of credit string in rsrc */
  108.     
  109.     /* Draw my picture. */
  110.     
  111.     mePict = GetPicture(mePictID);
  112.     HLock((Handle)mePict);
  113.     DrawPicture(mePict, &RectList[meRect]);
  114.     HUnlock((Handle)mePict);
  115.     
  116.     /* Draw the credits. */
  117.     
  118.     credits = GetResource('STR#', abouCreditsID);
  119.     MoveHHi(credits);
  120.     HLock(credits);
  121.     pCreditsStr = creditsStr;
  122.     nCreditsStr = **(short**)credits;
  123.     pCreditsRsrc = *credits+2;
  124.     while (nCreditsStr--) {
  125.         strLen = *pCreditsRsrc++;
  126.         memcpy(pCreditsStr, pCreditsRsrc, strLen);
  127.         pCreditsStr += strLen;
  128.         pCreditsRsrc += strLen;
  129.     };
  130.     HUnlock(credits);
  131.     TextFont(applFont);
  132.     TextSize(9);
  133.     TextBox(creditsStr, pCreditsStr-creditsStr, 
  134.         &RectList[creditsRect], teJustLeft);
  135.     TextFont(systemFont);
  136.     TextSize(0);
  137.         
  138.     /* Draw the movie in its current state. */
  139.     
  140.     if (State == slideNameLeft || State == slideNamesUp) {
  141.         CopyBits(&NameMap, &AbouWindow->portBits, &NameMap.bounds,
  142.             &NameMap.bounds, srcCopy, nil);
  143.     } else if (State == slideFootDown || State == slideFootUp) {
  144.         if (State == slideFootDown) 
  145.             CopyBits(&NameMap, &AbouWindow->portBits, &NamesRect,
  146.                 &SquishRect, srcCopy, nil);
  147.         CopyBits(&FootMap, &AbouWindow->portBits, &FootCopyRect,
  148.             &AbouCopyRect, srcCopy, nil);
  149.     };
  150. }
  151.  
  152. /*______________________________________________________________________
  153.  
  154.     Help - Process Mouse Down Event in Help Mode.
  155.     
  156.     Entry:        where = mouse down location, local coords.
  157. _____________________________________________________________________*/
  158.  
  159.  
  160. static void Help (Point where)
  161.  
  162. {
  163. #pragma unused (where)
  164.  
  165.     help_Open(tagAbouWind);
  166. }
  167.     
  168. /*______________________________________________________________________
  169.  
  170.     Close - Close the Window.
  171. _____________________________________________________________________*/
  172.  
  173.  
  174. static void Close (void)
  175.  
  176. {
  177.     Prefs.abouState.moved = AbouWindObject.moved;
  178.     wstm_Save(AbouWindow, &Prefs.abouState);
  179.     DisposeRgn(UpdateRgn);
  180.     DisposPtr(FootMap.baseAddr);
  181.     ClosePort(&NamePort);
  182.     DisposPtr(NameMap.baseAddr);
  183.     CloseWindow(AbouWindow);
  184.     AbouWindow = nil;
  185. };
  186.     
  187. /*______________________________________________________________________
  188.  
  189.     Adjust - Adjust Menus.
  190. _____________________________________________________________________*/
  191.  
  192.  
  193. static void Adjust (void)
  194.  
  195. {
  196.     MenuHandle                fileM;                    /* handle to file menu */
  197.     MenuHandle                editM;                    /* handle to edit menu */
  198.     MenuHandle                scanM;                    /* handle to scan menu */
  199.     MenuHandle                disinfectM;                /* handle to disinfect menu */
  200.     
  201.     fileM = GetMHandle(fileMID);
  202.     editM = GetMHandle(editMID);
  203.     scanM = GetMHandle(scanMID);
  204.     disinfectM = GetMHandle(disinfectMID);
  205.     EnableItem(fileM, closeCommand);
  206.     DisableItem(fileM, saveAsCommand);
  207.     DisableItem(fileM, pageSetupCommand);
  208.     DisableItem(fileM, printCommand);
  209.     DisableItem(fileM, printOneCommand);
  210.     DisableItem(editM, 0);
  211.     if (Scanning) {
  212.         DisableItem(fileM, quitCommand);
  213.         DisableItem(scanM, 0);
  214.         DisableItem(disinfectM, 0);
  215.     } else {
  216.         EnableItem(fileM, quitCommand);
  217.         EnableItem(scanM, 0);
  218.         EnableItem(disinfectM, 0);
  219.     };
  220. }
  221.     
  222. /*______________________________________________________________________
  223.  
  224.     Periodic - Perform Periodic Tasks.
  225. _____________________________________________________________________*/
  226.  
  227.  
  228. static void Periodic (void)
  229.  
  230. {
  231.     /* Static local variables.  These variables retain their values across
  232.         calls to this routine. */
  233.         
  234.     static short        windRight;        /* right coord of window */
  235.     static short        indVir;            /* index into virus info array */
  236.     static Str255        vName;            /* virus name */
  237.     static short        nameWidth;        /* width of virus name */
  238.     static short        stopAt;            /* coord to stop sliding at */
  239.     static Rect            scrollRect;        /* scrolling rectangle */
  240.     static short        footHeight;        /* height of foot */
  241.     static short        deltaSquish;    /* amount to expand squish rect each time */
  242.     static short        squishStart;    /* coord to start squishing */
  243.     static short        extraSquishStart;    /* coord to start squishing extra pixel */
  244.     static short        numNames;        /* number of names currently scrolled into
  245.                                                     view */
  246.     static Rect            eraseRect;        /* rectangle to be erased */
  247.     static short        namesTop;        /* top coord of NamesMap */
  248.                                                     
  249.     
  250.     /* Non-static local variables. */
  251.     
  252.     long                    ticks;            /* current tick count */
  253.     short                    extraWidth;        /* foot width minus virus names width */
  254.     short                    squishSteps;    /* number of squishing scrolls */
  255.     short                    extraSquish;    /* number of extra squishing pixels */
  256.         
  257.     ticks = TickCount();
  258.     if (ticks < WaitTill) return;
  259.     
  260.     switch (State) {
  261.     
  262.         case start:
  263.             
  264.             indVir = 1;
  265.             numNames = 0;
  266.             GetIndString(vName, abouVNamesID, indVir++);
  267.             windRight = AbouWindow->portRect.right;
  268.             SetPort(&NamePort);
  269.             EraseRect(&NameMap.bounds);
  270.             SetPort(AbouWindow);
  271.             State = startNameLeft;
  272.             WaitTill = ticks + initWait;
  273.             break;
  274.             
  275.         case startNameLeft:
  276.         
  277.             nameWidth = StringWidth(vName);
  278.             scrollRect.left = windRight-deltaNameHScroll;
  279.             scrollRect.right = windRight;
  280.             scrollRect.top = AbouWindow->portRect.bottom-40;
  281.             scrollRect.bottom = scrollRect.top+16;
  282.             stopAt = NamesLeft;
  283.             namesTop = NameMap.bounds.top;
  284.             State = slideNameLeft;
  285.             break;
  286.             
  287.         case slideNameLeft:
  288.         
  289.             SetPort(&NamePort);
  290.             ScrollRect(&scrollRect, -deltaNameHScroll, 0, UpdateRgn);
  291.             SetOrigin(NamesLeft, namesTop);
  292.             if (scrollRect.left + nameWidth + 4 >= windRight) {
  293.                 MoveTo(scrollRect.left, scrollRect.bottom-4);
  294.                 DrawString(vName);
  295.             };
  296.             SetPort(AbouWindow);
  297.             CopyBits(&NameMap, &AbouWindow->portBits, &scrollRect,
  298.                 &scrollRect, srcCopy, nil);
  299.             if (scrollRect.left - deltaNameHScroll < stopAt) {
  300.                 numNames++;
  301.                 GetIndString(vName, abouVNamesID, indVir++);
  302.                 if (*vName) {
  303.                     scrollRect.right = scrollRect.left + MaxNameWidth;
  304.                     scrollRect.top = scrollRect.bottom - 16*numNames - 
  305.                         deltaNameVScroll;
  306.                     stopAt = scrollRect.top - 16 + deltaNameVScroll;
  307.                     WaitTill = ticks + deltaNameVTicks;
  308.                     State = slideNamesUp;
  309.                 } else {
  310.                     stopAt = AbouWindow->portRect.bottom - 24;
  311.                     SquishRect = scrollRect;
  312.                     SquishRect.right = SquishRect.left + MaxNameWidth;
  313.                     SquishRect.top = SquishRect.bottom - 16*numNames;
  314.                     extraWidth = (FootMap.bounds.right - FootMap.bounds.left -
  315.                         MaxNameWidth) >> 1;
  316.                     squishSteps = (16*numNames-2)/deltaFootVScroll + 1;
  317.                     deltaSquish = extraWidth/squishSteps;
  318.                     extraSquish = extraWidth - deltaSquish*squishSteps;
  319.                     extraSquishStart = stopAt - deltaFootVScroll*extraSquish;
  320.                     squishStart = SquishRect.top;
  321.                     footHeight = FootMap.bounds.bottom - FootMap.bounds.top;
  322.                     FootCopyRect = FootMap.bounds;
  323.                     FootCopyRect.top = FootCopyRect.bottom;
  324.                     AbouCopyRect = FootCopyRect;
  325.                     AbouCopyRect.top = AbouCopyRect.bottom = 0;
  326.                     eraseRect = AbouCopyRect;
  327.                     NamesRect = SquishRect;
  328.                     WaitTill = ticks + footWait;
  329.                     State = slideFootDown;
  330.                 };
  331.             } else {
  332.                 scrollRect.left -= deltaNameHScroll;
  333.                 if (scrollRect.left + nameWidth + 4 < windRight) 
  334.                     scrollRect.right = scrollRect.left + nameWidth + 4;
  335.                 WaitTill = ticks + deltaNameHTicks;
  336.             };
  337.             break;
  338.             
  339.         case slideNamesUp:
  340.         
  341.             SetPort(&NamePort);
  342.             ScrollRect(&scrollRect, 0, -deltaNameVScroll, UpdateRgn);
  343.             SetOrigin(NamesLeft, namesTop);
  344.             SetPort(AbouWindow);
  345.             CopyBits(&NameMap, &AbouWindow->portBits, &scrollRect,
  346.                 &scrollRect, srcCopy, nil);
  347.             WaitTill = ticks + deltaNameVTicks;
  348.             scrollRect.top -= deltaNameVScroll;
  349.             scrollRect.bottom -= deltaNameVScroll;
  350.             if (scrollRect.top < stopAt) State = startNameLeft;
  351.             break;
  352.             
  353.         case slideFootDown:
  354.         
  355.             AbouCopyRect.bottom += deltaFootVScroll;
  356.             FootCopyRect.top -= deltaFootVScroll;
  357.             if (AbouCopyRect.bottom > footHeight) {
  358.                 AbouCopyRect.top = AbouCopyRect.bottom - footHeight;
  359.                 FootCopyRect.top = 0;
  360.                 eraseRect.bottom = AbouCopyRect.top;
  361.                 eraseRect.top = eraseRect.bottom - deltaFootVScroll;
  362.                 EraseRect(&eraseRect);
  363.             };
  364.             CopyBits(&FootMap, &AbouWindow->portBits,
  365.                 &FootCopyRect, &AbouCopyRect, srcCopy, nil);
  366.             if (AbouCopyRect.bottom < stopAt) {
  367.                 if (AbouCopyRect.bottom > squishStart) {
  368.                     SquishRect.top = AbouCopyRect.bottom;
  369.                     CopyBits(&NameMap, &AbouWindow->portBits, 
  370.                         &NamesRect, &SquishRect, srcCopy, nil);
  371.                     SquishRect.left -= deltaSquish;
  372.                     SquishRect.right += deltaSquish;
  373.                     if (AbouCopyRect.bottom > extraSquishStart) {
  374.                         SquishRect.left -= 1;
  375.                         SquishRect.right += 1;
  376.                     };
  377.                     WaitTill = ticks + deltaSquishVTicks; 
  378.                 } else {
  379.                     WaitTill = ticks + deltaFootVTicks;
  380.                 };
  381.                 scrollRect.bottom += deltaFootVScroll;
  382.             } else {
  383.                 eraseRect = AbouCopyRect;
  384.                 eraseRect.top = eraseRect.bottom - deltaFootVScroll;
  385.                 State = slideFootUp;
  386.                 WaitTill = ticks + deltaFootVTicks;
  387.             };
  388.             break;
  389.             
  390.         case slideFootUp:
  391.         
  392.             EraseRect(&eraseRect);
  393.             OffsetRect(&eraseRect, 0, -deltaFootVScroll);
  394.             OffsetRect(&AbouCopyRect, 0, -deltaFootVScroll);
  395.             if (AbouCopyRect.bottom < footHeight) {
  396.                 AbouCopyRect.top = 0;
  397.                 FootCopyRect.top = footHeight - AbouCopyRect.bottom;
  398.             };
  399.             CopyBits(&FootMap, &AbouWindow->portBits,
  400.                 &FootCopyRect, &AbouCopyRect, srcCopy, nil);
  401.             if (AbouCopyRect.bottom > 0) {
  402.                 WaitTill = ticks + deltaFootVTicks;
  403.             } else {
  404.                 WaitTill = ticks;
  405.                 State = start;
  406.             };
  407.             break;
  408.             
  409.     };
  410.             
  411. }
  412.     
  413. /*______________________________________________________________________
  414.  
  415.     abou_Open - Open Abou Window.
  416. _____________________________________________________________________*/
  417.  
  418.  
  419. void abou_Open (void)
  420.  
  421. {
  422.     GrafPort            footPort;            /* grafPort for drawing foot offscreen */
  423.     PicHandle        footPict;            /* handle to foot picture */
  424.     short                indVir;                /* loop index */
  425.     Str255            vName;                /* virus name */
  426.     short                nameWidth;            /* width of virus name */
  427.     short                numVNames;            /* number of virus names */
  428.     
  429.     /* Get the about window and restore its state. */
  430.     
  431.     AbouWindow = wstm_Restore(false, abouWindID, (Ptr)&AbouWRecord,
  432.         &Prefs.abouState);
  433.     SetPort(AbouWindow);
  434.     
  435.     /* Initialize the window object. */
  436.     
  437.     ((WindowPeek)AbouWindow)->refCon = (long)&AbouWindObject;
  438.     AbouWindObject.windKind = abouWind;
  439.     AbouWindObject.moved = Prefs.abouState.moved;
  440.     AbouWindObject.update = Update;
  441.     AbouWindObject.activate = nil;
  442.     AbouWindObject.deactivate = nil;
  443.     AbouWindObject.click = nil;
  444.     AbouWindObject.help = Help;
  445.     AbouWindObject.grow = nil;
  446.     AbouWindObject.zoom = nil;
  447.     AbouWindObject.key = nil;
  448.     AbouWindObject.close = Close;
  449.     AbouWindObject.disk = nil;
  450.     AbouWindObject.save = nil;
  451.     AbouWindObject.pageSetup = nil;
  452.     AbouWindObject.print = nil;
  453.     AbouWindObject.edit = nil;
  454.     AbouWindObject.adjust = Adjust;
  455.     AbouWindObject.periodic = Periodic;
  456.     AbouWindObject.dialogPre = nil;
  457.     AbouWindObject.dialogPost = nil;
  458.     
  459.     /* Create the update region for the ScrollRect calls. */
  460.     
  461.     UpdateRgn = NewRgn();
  462.     
  463.     /* Allocate and initialize the offscreen foot bitmap. */
  464.     
  465.     FootMap.bounds = RectList[footRect];
  466.     FootMap.rowBytes = (((FootMap.bounds.right-FootMap.bounds.left+7)>>3) + 1) 
  467.         & 0xfffe;
  468.     FootMap.baseAddr = NewPtr(FootMap.rowBytes*(FootMap.bounds.bottom-
  469.         FootMap.bounds.top));
  470.     
  471.     /* Draw the foot picture in the offscreen bitmap. */
  472.     
  473.     OpenPort(&footPort);
  474.     SetPortBits(&FootMap);
  475.     footPort.portRect = RectList[footRect];
  476.     ClipRect(&footPort.portRect);
  477.     EraseRect(&footPort.portRect);
  478.     footPict = GetPicture(footPictID);
  479.     HLock((Handle)footPict);
  480.     DrawPicture(footPict, &footPort.portRect);
  481.     HUnlock((Handle)footPict);
  482.     ClosePort(&footPort);
  483.     SetPort(AbouWindow);
  484.     
  485.     /* Allocate the offscreen virus names bitmap and grafport. */
  486.     
  487.     MaxNameWidth = 0;
  488.     TextFont(systemFont);
  489.     TextSize(0);
  490.     numVNames = 0;
  491.     for (indVir = 1; ; indVir++) {
  492.         GetIndString(vName, abouVNamesID, indVir);
  493.         if (!*vName) break;
  494.         numVNames++;
  495.         nameWidth = StringWidth(vName);
  496.         if (nameWidth > MaxNameWidth) MaxNameWidth = nameWidth;
  497.     };
  498.     NamesLeft = (RectList[footRect].right + RectList[footRect].left 
  499.         - MaxNameWidth) >> 1;
  500.     SetRect(&NameMap.bounds, NamesLeft, 
  501.         AbouWindow->portRect.bottom - 24 - 16*numVNames,
  502.         AbouWindow->portRect.right,
  503.         AbouWindow->portRect.bottom - 24);
  504.     NameMap.rowBytes = (((NameMap.bounds.right-NameMap.bounds.left+7)>>3) + 1) & 
  505.         0xfffe;
  506.     NameMap.baseAddr = NewPtr(NameMap.rowBytes * 16 * numVNames);
  507.     OpenPort(&NamePort);
  508.     SetPortBits(&NameMap);
  509.     NamePort.portRect = NameMap.bounds;
  510.     ClipRect(&NamePort.portRect);
  511.     SetPort(AbouWindow);
  512.     
  513.     /* Initialize the WaitTill and State variables. */
  514.     
  515.     WaitTill = 0;
  516.     State = start;    
  517.     
  518.     /* Show the about window. */
  519.     
  520.     ShowWindow(AbouWindow);
  521. }